package v1

import (
	"errors"
	"log"
	"net/http"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"gitee.com/laofa1/play/k_conf_mng/kconf_backend/models"
	"gitee.com/laofa1/play/k_conf_mng/kconf_backend/pkg/instancecreate"
	"gorm.io/gorm"
)

// params:
//   env_name
//	 docker_node_name:
type EnvParam struct {
	EnvName string `json:"envName"`
}

type DeleteParam struct {
	ID int `json:"id"`
}

type CreateState struct {
	JenkinsCreateState string `json:"jenkins_create_state"`
	NginxCreateState   string `json:"nginx_create_state"`
	DBCreateState      string `json:"db_create_state"`
	RedisCreateState   string `json:"redis_create_state"`
}

func DeleteEnv(c *gin.Context) {
	var deleteParam DeleteParam
	err := c.BindJSON(&deleteParam)
	if err != nil {
		log.Println(err)
		return
	}

	err = instancecreate.DeleteInstance(strconv.Itoa(deleteParam.ID))
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   "try to delete env error",
		})
		return
	}
}

func CreateEnv(c *gin.Context) {
	var createParam EnvParam
	err := c.BindJSON(&createParam)
	if err != nil {
		log.Println(err)
		return
	}
	// need to check envname
	if strings.ToLower(createParam.EnvName) != createParam.EnvName || len(createParam.EnvName) == 0 {
		errMsg := "env name should not be blank and only lower chara allowed."
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   errMsg,
		})
		return
	}
	userID := c.MustGet("userID").(uint64)
	user, err := models.GetUser(userID)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   err.Error(),
		})
		return
	}

	// check if the env instance already exists
	_, err = models.GetEnvInstance(createParam.EnvName, "Name")
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			log.Println(err)
			c.JSON(http.StatusOK, gin.H{
				"status": "error",
				"data":   err.Error(),
			})
			return
		}
	} else {
		// err is nil indict find the env
		log.Println(createParam.EnvName, "is already exist")
		c.JSON(http.StatusBadRequest, gin.H{
			"status": "error",
			"data":   createParam.EnvName + " is already exist",
		})
		return
	}

	err = instancecreate.CreateInstance(createParam.EnvName, user.UserName)
	if err != nil {
		log.Println(err)
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"status": "ok",
		"data":   "instance is creating",
	})
	return
}

func GetEnvStates(c *gin.Context) {
	var queryParam EnvParam
	err := c.BindQuery(&queryParam)
	if err != nil {
		log.Println(err)
		return
	}
	// need to check envname
	if strings.ToLower(queryParam.EnvName) != queryParam.EnvName || len(queryParam.EnvName) == 0 {
		errMsg := "env name should not be blank and only lower chara allowed."
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   errMsg,
		})
		return
	}

	instance, err := models.GetEnvInstance(queryParam.EnvName, "Name")
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			log.Println(err)
			c.JSON(http.StatusOK, gin.H{
				"status": "error",
				"data":   err.Error(),
			})
			return
		}
	} else {
		data := CreateState{
			JenkinsCreateState: instance.JenkinsCreateState,
			NginxCreateState:   instance.NginxCreateState,
			RedisCreateState:   instance.RedisCreateState,
			DBCreateState:      instance.DBCreateState,
		}
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"data":   data,
		})
		return
	}

}

func GetEnvsStates(c *gin.Context) {
	instances, err := models.GetAllEnvInstances()
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			log.Println(err)
			c.JSON(http.StatusOK, gin.H{
				"status": "error",
				"data":   err.Error(),
			})
			return
		}
	} else {
		// process instances to get state
		var states []CreateState
		for _, eachInstance := range instances {
			states = append(states, CreateState{
				JenkinsCreateState: eachInstance.JenkinsCreateState,
				NginxCreateState:   eachInstance.NginxCreateState,
				RedisCreateState:   eachInstance.RedisCreateState,
				DBCreateState:      eachInstance.DBCreateState,
			})
		}
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"data":   states,
		})
		return
	}
}

func GetEnv(c *gin.Context) {
	var queryParam EnvParam
	err := c.BindQuery(&queryParam)
	if err != nil {
		log.Println(err)
		return
	}
	// need to check envname
	if strings.ToLower(queryParam.EnvName) != queryParam.EnvName || len(queryParam.EnvName) == 0 {
		errMsg := "env name should not be blank and only lower chara allowed."
		c.JSON(http.StatusOK, gin.H{
			"status": "error",
			"data":   errMsg,
		})
		return
	}

	instance, err := models.GetEnvInstance(queryParam.EnvName, "Name")
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			log.Println(err)
			c.JSON(http.StatusOK, gin.H{
				"status": "error",
				"data":   err.Error(),
			})
			return
		}
	} else {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"data":   instance,
		})
		return
	}

}
func GetEnvs(c *gin.Context) {
	instances, err := models.GetAllEnvInstances()
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			log.Println(err)
			c.JSON(http.StatusOK, gin.H{
				"status": "error",
				"data":   err.Error(),
			})
			return
		}
	} else {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"data":   instances,
		})
		return
	}
}
